"""
/*
 * Copyright 2011 OpenWAF.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
 """
import Analyzer
from Analyzer import SGlobal

def analyze(rcls):
    um=Analyzer.SGlobal.used_methods
    processed=Analyzer.SGlobal.processed_refs
    if len(um)==0:
        cls=Analyzer.SHelper.getClassOnFullName("com.openwaf.core.framework.BlockMethod")
        analyzeImpl(cls,um,processed)
        cls=Analyzer.SHelper.getClassOnFullName("com.openwaf.core.framework.ArrayUtil")
        analyzeImpl(cls,um,processed)
        cls=Analyzer.SHelper.getClassOnFullName("com.openwaf.core.framework.Autoboxing")
        analyzeImpl(cls,um,processed)
        cls=Analyzer.SHelper.getClassOnFullName("com.openwaf.core.framework.TypeCast")
        analyzeImpl(cls,um,processed)
        cls=Analyzer.SHelper.getClassOnFullName("com.openwaf.core.framework.RunTimeHelper")
        analyzeImpl(cls,um,processed)
        cls=Analyzer.SHelper.getClassOnFullName("com.openwaf.client.core.Client")
        analyzeImpl(cls,um,processed)
        cls=Analyzer.SHelper.getClassOnFullName("java.lang.Object")
        analyzeImpl(cls,um,processed)
        cls=Analyzer.SHelper.getClassOnFullName("java.util.Iterator")
        analyzeImpl(cls,um,processed)
        cls=Analyzer.SHelper.getClassOnFullName("java.lang.Iterable")
        analyzeImpl(cls,um,processed)
        cls=Analyzer.SHelper.getClassOnFullName("java.lang.Throwable")
        analyzeImpl(cls,um,processed)            
        for i in Analyzer.SGlobal.static_refs:
            um.append(i)
            if i in processed:continue
            processed.append(i)
            if Analyzer.SGlobal.method_refs.has_key(i):
                collect_methods(Analyzer.SGlobal.method_refs[i], um,processed)
    analyzeImpl(rcls,um,processed)
    um=list(set(um))
    while True:
        tum=checkAbstractMethod(um,processed)
        if tum==None:
            break
        um=tum
    while True:
        tum=checkOverridedMethod(um, processed)
        if tum==None:
            break
        um=tum
    um=list(set(um))
    ##mark implemented method as well             
    Analyzer.SGlobal.used_methods=um
def getOverridedMethods(mid,methods):
    if SGlobal.omid.has_key(mid):        
        for m in SGlobal.omid[mid]:
            if not methods.has_key[m.mid]:
                methods[m.mid]=m
            getOverridedMethods(m.mid, methods)
def checkOverridedMethod(um,processed):    
    nm=[]
    for i in um:
        if not SGlobal.omid.has_key(i):continue
        methods={}
        getOverridedMethods(i, methods)
        for k in methods:
            if k in processed:continue
            m=methods[k]            
            nm.append(m.mid)                    
            processed.append(m.mid)
            if Analyzer.SGlobal.method_refs.has_key(m.mid):
                collect_methods(Analyzer.SGlobal.method_refs[m.mid],nm,processed)
    if len(nm)==0:
        return None
    return nm+um

        
def checkAbstractMethod(um,processed):
    found=True
    nm=[]
    for i in Analyzer.SGlobal.method_refs:
        m=Analyzer.SGlobal.method_refs[i]
        if m.imid==None:continue
        found=False
        for im in m.imid:
            if im.mid in um:
                found=True
                break        
        if found==False:continue
        if m.mid in processed:continue            
        nm.append(m.mid)                    
        processed.append(m.mid)
        if Analyzer.SGlobal.method_refs.has_key(m.mid):
            collect_methods(Analyzer.SGlobal.method_refs[m.mid],nm,processed)
    if len(nm)==0:
        return None
    return nm+um
            
            
       
def analyzeImpl(cls,um,processed):
    
    processed=[]
    for m in cls.methods:
        um.append(m.mid)
        collect_methods(m, um,processed)
    if not cls.isClass():return
    for m in cls.constructors:
        um.append(m.mid)
        collect_methods(m, um,processed)
    
    
def collect_methods(m,um,processed):
    for i in m.refs:
        um.append(i)
        if i in processed:continue
        processed.append(i)
        if Analyzer.SGlobal.method_refs.has_key(i):
            collect_methods(Analyzer.SGlobal.method_refs[i], um,processed)
    
    
